<template>
  <div class="navigation-demo">
    <div id="map" class="map-container"></div>
    <div class="navigation-info">
      <div class="info-panel">
        <div class="info-item">
          <span class="label">剩余距离</span>
          <span class="value">{{ remainingDistance }}米</span>
        </div>
        <div class="info-item">
          <span class="label">预计时间</span>
          <span class="value">{{ remainingTime }}分钟</span>
        </div>
        <div class="info-item">
          <span class="label">当前速度</span>
          <span class="value">{{ currentSpeed }}km/h</span>
        </div>
      </div>
    </div>
    <div class="control-panel">
      <button @click="startNavigation" :disabled="isNavigating">
        <span class="icon">▶</span>
        开始导航
      </button>
      <button @click="pauseNavigation" :disabled="!isNavigating">
        <span class="icon">⏸</span>
        暂停导航
      </button>
      <button @click="resetNavigation">
        <span class="icon">⟲</span>
        重置
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'
import mapboxgl, { LngLat } from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'
import * as turf from '@turf/turf'
import arrow from '../assets/images/arrow.png'

// 模拟导航路线坐标点 (更真实的路线)
const routeCoordinates: [number, number][] = [
    [
        116.38954197255936,
        39.90394890520642
    ],
    [
        116.3894374783356,
        39.90597137051165
    ],
    [
        116.39308604250408,
        39.90613564178821
    ]
]

const map = ref<mapboxgl.Map | null>(null)
const marker = ref<mapboxgl.Marker | null>(null)
const currentDistance = ref(0)
const isNavigating = ref(false)
const animationFrameId = ref<number | null>(null)
const lastTimestamp = ref<number>(0)
const currentSpeed = ref(120) // 初始速度到 20km/h

// 创建路线的 LineString
const routeLine = computed(() => {
  return turf.lineString(routeCoordinates)
})

// 计算路线总长度（米）
const totalDistance = computed(() => {
  return turf.length(routeLine.value, { units: 'meters' })
})

// 计算剩余距离
const remainingDistance = computed(() => {
  return Math.round(totalDistance.value - currentDistance.value)
})

// 计算预计剩余时间（分钟）
const remainingTime = computed(() => {
  const speed = currentSpeed.value / 3.6 // 转换为米/秒
  return Math.max(1, Math.round((remainingDistance.value / speed) / 60))
})

// 初始化地图
const initMap = () => {
  mapboxgl.accessToken = import.meta.env.VITE_APP_MAP_TOKEN
  map.value = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v11',
    center: routeCoordinates[0],
    zoom: 16,
    pitch: 45 // 添加相机倾斜角度
  })

  map.value.on('load', () => {
    if (!map.value) return

    // 添加路线图层
    map.value.addSource('route', {
      type: 'geojson',
      data: routeLine.value
    })

    map.value.addLayer({
      id: 'route',
      type: 'line',
      source: 'route',
      layout: {
        'line-join': 'round',
        'line-cap': 'round'
      },
      paint: {
        'line-color': '#00ff00',//绿色
        'line-width': 15,
        'line-opacity': 0.9
      }
    })

    // 添加导航标记（使用自定义箭头标记）
    const el = document.createElement('div')
    el.className = 'navigation-marker'
    el.innerHTML = `<img src="${arrow}" style="width: 64px; height: 64px;" alt="arrow" />`
    el.style.fontSize = '24px'

    marker.value = new mapboxgl.Marker({
      element: el,
      rotationAlignment: 'map'
    })
      .setLngLat(routeCoordinates[0])
      .addTo(map.value)
  })

 

}

// 获取路线上的点位置
const getPositionAlongRoute = (distance: number): [number, number] => {
  try {
    if (distance <= 0) return routeCoordinates[0]
    if (distance >= totalDistance.value) return routeCoordinates[routeCoordinates.length - 1]

    const point = turf.along(routeLine.value, distance / 1000, { units: 'kilometers' })
    return point.geometry.coordinates as [number, number]
  } catch (error) {
    console.error('Error calculating position:', error)
    return routeCoordinates[0]
  }
}

// 计算路线上某点的方向角度
const calculateBearing = (distance: number): number => {
  try {
    const currentPoint = getPositionAlongRoute(distance)
    const aheadPoint = getPositionAlongRoute(Math.min(distance + 5, totalDistance.value))
    return turf.bearing(
      turf.point(currentPoint),
      turf.point(aheadPoint)
    )
  } catch (error) {
    console.error('Error calculating bearing:', error)
    return 0
  }
}

// 动画函数
const animate = (timestamp: number) => {
  if (!isNavigating.value) return

  if (!lastTimestamp.value) {
    lastTimestamp.value = timestamp
    animationFrameId.value = requestAnimationFrame(animate)
    return
  }

  const deltaTime = timestamp - lastTimestamp.value
  // const speed = currentSpeed.value / 3.6 // 转换为米/秒
  const speed = currentSpeed.value // 转换为米/秒
  const distanceDelta = (deltaTime / 1000) * speed

  const newDistance = currentDistance.value + distanceDelta
  if (newDistance >= totalDistance.value) {
    isNavigating.value = false
    currentDistance.value = totalDistance.value
    return
  }

  currentDistance.value = newDistance
  const position = getPositionAlongRoute(currentDistance.value)
  const bearing = calculateBearing(currentDistance.value)

  if (marker.value && position) {
    marker.value
      .setLngLat(position)
      .setRotation(bearing)

    // 更新地图视角，添加前瞻性视角
    const lookAheadDistance = Math.min(currentDistance.value + 30, totalDistance.value) // 前看30米
    const lookAheadPosition = getPositionAlongRoute(lookAheadDistance)
    
    map.value?.easeTo({
      center: lookAheadPosition,
      bearing: bearing,
      duration: 50,
      pitch: 45
    })
  }

  lastTimestamp.value = timestamp
  animationFrameId.value = requestAnimationFrame(animate)
}

// 开始导航
const startNavigation = () => {
  if (isNavigating.value) return
  isNavigating.value = true
  lastTimestamp.value = 0
  animate(performance.now())
}

// 暂停导航
const pauseNavigation = () => {
  isNavigating.value = false
  if (animationFrameId.value) {
    cancelAnimationFrame(animationFrameId.value)
  }
}

// 重置导航
const resetNavigation = () => {
  isNavigating.value = false
  currentDistance.value = 0
  lastTimestamp.value = 0
  if (animationFrameId.value) {
    cancelAnimationFrame(animationFrameId.value)
  }
  if (marker.value) {
    marker.value
      .setLngLat(routeCoordinates[0])
      .setRotation(0)
  }
  map.value?.easeTo({
    center: routeCoordinates[0],
    zoom: 16,
    pitch: 45,
    bearing: 0,
    duration: 1000
  })
}

onMounted(() => {
  initMap()
})

onUnmounted(() => {
  if (animationFrameId.value) {
    cancelAnimationFrame(animationFrameId.value)
  }
  map.value?.remove()
})
</script>

<style scoped>
.navigation-demo {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.map-container {
  width: 100%;
  height: 100%;
}

.navigation-info {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1;
}

.info-panel {
  background: rgba(255, 255, 255, 0.9);
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: flex;
  gap: 20px;
}

.info-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.label {
  font-size: 12px;
  color: #666;
  margin-bottom: 4px;
}

.value {
  font-size: 16px;
  font-weight: bold;
  color: #333;
}

.control-panel {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.9);
  padding: 10px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: flex;
  gap: 10px;
}

button {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  background: #3887be;
  color: white;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.2s;
}

button:disabled {
  background: #ccc;
  cursor: not-allowed;
}

button:hover:not(:disabled) {
  background: #2d6a94;
}

.icon {
  font-size: 16px;
}

:deep(.navigation-marker) {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  transform-origin: center;
  transform: translate(-50%, -50%);
}
</style>